package manager;

import helper.PatientResult;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;

import util.AppUtil;
import util.HibernateUtil;
import bean.PatientEnvironmentalExposure;
import bean.PatientGeneralInfo;
import bean.PatientPastHistory;
import bean.labTests.BloodPressure;
import bean.labTests.GlucoseTest;
import bean.labTests.InsulinTest;
import bean.labTests.LipidProfile;


public class PatientManager {
	
	  Session session = null;
	
	public PatientManager(){
		
	}
	
	
	public String insertPatientGeneralInfo(String firstName,String middleName,String lastName,String sex,String ethnicity, String birthCountry,
											String ssn, String addressLine1,String addressLine2, String city,  String state, long zip, 
											Date dateOfBirth, String homePhone, String workPhone, String email, String username,String password){

		Serializable savedId = null;
		try{
			
			
			if(this.isDuplicate(username)){
				
				return "duplicateUsername";
			}
			Calendar calendar = Calendar.getInstance();
			//Create an instance of patient general info
			PatientGeneralInfo pg = new PatientGeneralInfo();
			pg.setFirstName(firstName);
			pg.setLastName(lastName);
			pg.setAddressLine1(addressLine1);
			pg.setAddressLine2(addressLine2);
			pg.setBirthCountry(birthCountry);
			pg.setCity(city);
			pg.setDateOfBirth(dateOfBirth);
			pg.setEmail(email);
			pg.setEthnicity(ethnicity);
			pg.setFirstName(firstName);
			pg.setHomePhone(homePhone);
			pg.setLastName(lastName);
			pg.setMiddleName(middleName);
			pg.setPassword(password);
			pg.setSex(sex);
			pg.setSsn(ssn);
			pg.setState(state);
			pg.setUsername(username);
			pg.setWorkPhone(workPhone);
			pg.setZip(zip);
			pg.setLastUpdated(calendar.getTime());
			
			//Prepare session
			session = HibernateUtil.prepareSession();
			//Create transaction
			Transaction t = session.beginTransaction();
			//Save record
			savedId = session.save(pg);
			
			session.flush();
			//commit transaction
			t.commit();
			
		}catch(Exception ex){
			ex.printStackTrace();
		}
		finally{
			
			HibernateUtil.closeSession(session);
			//
			
			
		}
		//		return created patient id.
		return savedId.toString();	}
	
	
	/**
	 * Check if the username already exists in the database. If it does, return true otherwise false.
	 * @param username
	 * @return
	 */
	boolean isDuplicate(String username){
		
		session = HibernateUtil.prepareSession();
		String QUERY = "select count(pg) from PatientGeneralInfo pg where lower(pg.username) = '" + username.trim().toLowerCase() + "'";
		Query hql = session.createQuery(QUERY);
		List result = hql.list();
		
		HibernateUtil.closeSession(session);
		
		
		
		if(result.get(0).toString().equalsIgnoreCase("0"))
			return false;
		
		return true;
		
	}
	
	
	
	/**
	 * List all the patients
	 * @return
	 */
	public List<PatientResult> listPatients(){
		//Prepare session
		session = HibernateUtil.prepareSession();
		
		String QUERY = " select new helper.PatientResult(pg.id,pg.firstName, pg.middleName, pg.lastName, " +
				"(select count(p) from PatientPersonalInfo p where p.patientId = pg.id) as countPersonalInfo, " +
				"(select count(p) from PatientPastHistory p where p.patientId = pg.id) as countPastHistory," +
				"(select count(p) from PatientEnvironmentalExposure p where p.patientId = pg.id) ,"+
				"pg.lastUpdated) from PatientGeneralInfo pg order by pg.lastUpdated desc";
		
		Query hql = session.createQuery(QUERY);
		List<PatientResult> lstPatientGeneralInfo = hql.list();
		
		
		HibernateUtil.closeSession(session);
		return lstPatientGeneralInfo;
	}
	
		
	/**
	 * 
	 * @param patientId
	 * @return
	 */
	public PatientGeneralInfo getPatientSummary(long patientId){
		session = HibernateUtil.prepareSession();		
		PatientGeneralInfo generalInfo = (PatientGeneralInfo)session.get(PatientGeneralInfo.class, patientId);		
		HibernateUtil.closeSession(session);		
		return generalInfo;
	}
	
	
	public PatientGeneralInfo getPatientDetails(long patientId){
		
		Calendar calendar = Calendar.getInstance();
		Date endDate = calendar.getTime();
		calendar.add(Calendar.YEAR, -1);
		Date startDate = calendar.getTime();
				
		PatientGeneralInfo pg = this.getPatientSummary(patientId);
		session = HibernateUtil.prepareSession();
		Criteria bpCrit = session.createCriteria(BloodPressure.class).add(Restrictions.eq("patientId", patientId))
								.add(Restrictions.between("testDate", startDate, endDate));
		
		Criteria gtCrit = session.createCriteria(GlucoseTest.class).add(Restrictions.eq("patientId", patientId))
								.add(Restrictions.between("testDate", startDate, endDate));
		
		Criteria lpCrit = session.createCriteria(LipidProfile.class).add(Restrictions.eq("patientId", patientId))
		.add(Restrictions.between("testDate", startDate, endDate));
		
		Criteria insCrit = session.createCriteria(InsulinTest.class).add(Restrictions.eq("patientId", patientId))
		.add(Restrictions.between("testDate", startDate, endDate));
		
		pg.setBloodPressureReadings(new HashSet(bpCrit.list()));
		pg.setGlucoseTests(new HashSet(gtCrit.list()));
		pg.setLipidTests(new HashSet(lpCrit.list()));
		pg.setInsulinTests(new HashSet(insCrit.list()));
		
		HibernateUtil.closeSession(session);
		
		return pg;
		
		
	}
	
	/**
	 * 
	 * @param patientId
	 * @param systolic
	 * @param diastolic
	 * @param testDate
	 * @return
	 */
	
	public String addBloodPressure(long patientId, double systolic, double diastolic, Date testDate){
		
		String message = null;
		try{
			BloodPressure bp = new BloodPressure();
			bp.setSystolic(systolic);
			bp.setDiastolic(diastolic);
			bp.setTestDate(testDate);
			bp.setPatientId(patientId);		
			//Prepare session
			session = HibernateUtil.prepareSession();
			//Begin transaction
			HibernateUtil.startTransaction(session);
			    PatientGeneralInfo pg = (PatientGeneralInfo)session.get(PatientGeneralInfo.class, patientId);
			    pg.setLastUpdated(Calendar.getInstance().getTime());
			    pg.getBloodPressureReadings().add(bp);
			    session.flush();
			//commit transaction
		   HibernateUtil.commitTransaction();
		    message =  "Success";
		}catch(Exception ex){
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
			message = "Failure";
		}finally{
			HibernateUtil.closeSession(session);
			return message;			
		}	
		
	}
	
	public String addGlucoseTest(long patientId, double fastingGlucose, double ogtt, Date testDate){
		
		String message = null;
		try{
			GlucoseTest gt = new GlucoseTest();
			gt.setFastingGlucose(fastingGlucose);
			gt.setOgtt(ogtt);
			gt.setTestDate(testDate);
			gt.setPatientId(patientId);		
			//Prepare session
			session = HibernateUtil.prepareSession();
			//Begin transaction
			HibernateUtil.startTransaction(session);
			    PatientGeneralInfo pg = (PatientGeneralInfo)session.get(PatientGeneralInfo.class, patientId);
			    pg.setLastUpdated(Calendar.getInstance().getTime());
			    pg.getGlucoseTests().add(gt);
			    session.flush();
			//commit transaction
		   HibernateUtil.commitTransaction();
		    message =  "Success";
		}catch(Exception ex){
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
			message = "Failure";
		}finally{
			HibernateUtil.closeSession(session);
			return message;			
		}	
		
	}
	
	
	public String addPatientPastMedicalHistory(boolean asthma, boolean kidneyDisease,
			boolean depression, boolean diabetes, boolean eatingDisorder,
			boolean heartDisorder, boolean highBloodPressure,
			boolean highCholestrol, boolean thyroidDisease,
			boolean tuberculosis, long patientID) {
		
		
		String message = null;
		
		try{
			PatientPastHistory pph = new PatientPastHistory(asthma, kidneyDisease, depression, 
					diabetes, eatingDisorder, heartDisorder, highBloodPressure, highCholestrol, thyroidDisease, tuberculosis, patientID);
			
			//Prepare session
			session = HibernateUtil.prepareSession();
			//Begin transaction
			HibernateUtil.startTransaction(session);
				PatientGeneralInfo pg = (PatientGeneralInfo)session.get(PatientGeneralInfo.class, patientID); 
				pg.setPastHistory(pph);
				pg.setLastUpdated(AppUtil.getCurrentTime());
				session.flush();
			HibernateUtil.commitTransaction();
			message = "Success";
			
		}catch(Exception ex){
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
			message = "Failure";
			
		}
		finally{
			HibernateUtil.closeSession(session);
			return message;
		}
		
	}
	
	public String addEnvironmentalExposure(boolean asbestos, boolean lead,
			boolean diesel, boolean dust, boolean chemicals, long patientId){
		String message = null;
		
		try{
			PatientEnvironmentalExposure pee = new PatientEnvironmentalExposure(asbestos, lead, diesel, dust, chemicals, patientId);			
			//Prepare session
			session = HibernateUtil.prepareSession();
			//Begin transaction
			HibernateUtil.startTransaction(session);
				PatientGeneralInfo pg = (PatientGeneralInfo)session.get(PatientGeneralInfo.class, patientId); 
				pg.setEnvironmentalExposure(pee);
				pg.setLastUpdated(AppUtil.getCurrentTime());
				session.flush();
			HibernateUtil.commitTransaction();
			message = "Success";
			
		}catch(Exception ex){
			ex.printStackTrace();
			HibernateUtil.rollbackTransaction();
			message = "Failure";
			
		}
		finally{
			HibernateUtil.closeSession(session);
			return message;
		}
		
	}
	
	public PatientPastHistory getPatientPastHistory(long patientId){
		session = HibernateUtil.prepareSession();		
		PatientPastHistory ph = (PatientPastHistory)session.get(PatientPastHistory.class, patientId);		
		HibernateUtil.closeSession(session);		
		return ph;		
	}
	
	public PatientEnvironmentalExposure getEnvironmentalExposure(long patientId){
		session = HibernateUtil.prepareSession();		
		PatientEnvironmentalExposure pe = (PatientEnvironmentalExposure)session.get(PatientEnvironmentalExposure.class, patientId);		
		HibernateUtil.closeSession(session);		
		return pe;	
	}
	
	public static void main(String args[]){
		//new PatientManager().addPatientPastMedicalHistory(true, true, true, true, true, true, 
		//		true,true, true, true, 1);
		
		System.out.println(new PatientManager().getPatientDetails(1));
		
	}
	

}
